#include "Simulator.hh"


//constructor
Simulator::Simulator(void)
{
    gameover = 0;
    turn = 0;
    bug.open("./debug.sim");
};


Simulator::Simulator(const State & s)
{
  rows = s.rows;
  cols = s.cols;
  turn = s.turn;
  turns = s.turns;
  attackradius = s.attackradius;
  spawnradius = s.spawnradius;
  viewradius = s.spawnradius;
  loadtime = s.loadtime;
  turntime = s.turntime;
  scores = scores;
  gameover = s.gameover;
  seed = s.seed;
  grid = s.grid;
  
  myAnts = s.myAnts;
  enemyAnts = s.enemyAnts;
  myHills = s.myHills;
  enemyHills = s.enemyHills;
  food = s.food;
  timer = s.timer;
 
  
}




void 
Simulator::simulate_one_step(Order & myOrder)
{
  const bool simulation = true;

  myOrder.execute(*this,simulation);

  death = solve_battles(*this);
    
}



struct count_enemys_t
{
  Location myloc;
  
  count_enemys_t(Location & _myloc)
    : myloc(_myloc)
  {
  }
  
  bool operator()(State & s, Ploc & ploc)
  {
    unsigned myteam = s.grid[myloc.row][myloc.col].ant;
    if(s.grid[ploc.row][ploc.col].ant>0 and
       s.grid[ploc.row][ploc.col].ant != myteam)
      s.grid[ploc.row][ploc.col].enemys ++;
    return true;
  }

};


struct search_and_kill_t
{
  Location myloc;
  
  search_and_kill_t(Location & _myloc)
    : myloc(_myloc)
  {
  }
  
  bool operator()(State & s, Ploc & ploc)
  {
    unsigned myteam = s.grid[myloc.row][myloc.col].ant;
    if(s.grid[ploc.row][ploc.col].ant!=-1 and
       s.grid[ploc.row][ploc.col].ant != myteam and 
       s.grid[myloc.row][myloc.col].enemys >= s.grid[ploc.row][ploc.col].enemys)
      {
	s.grid[myloc.row][myloc.col].isDead = true;
	return false;
      }
    return true;
  }

};



signed
Simulator::solve_battles(State & s)
{

  // 1 - Count enemys
  for(int row=0; row<rows; row++)
    for(int col=0; col<cols; col++)
      {
	grid[row][col].enemys = 0;
	grid[row][col].isDead = false;
      }
  
  for(unsigned i=0; i!=s.myAnts.size(); ++i)
    {
      count_enemys_t attak(s.myAnts[i]);
      fly(s, s.myAnts[i], s.attackradius, attak);
    }

  for(unsigned i=0; i!=s.enemyAnts.size(); ++i)
    {
      count_enemys_t attak(s.enemyAnts[i]);
      fly(s, s.enemyAnts[i], s.attackradius, attak);
    }

  // 2 - Compare enemy counts
  signed death = 0;
  for(unsigned i=0; i!=s.myAnts.size(); ++i)
    {
      search_and_kill_t defend(s.myAnts[i]);
      fly(s, s.myAnts[i], s.attackradius, defend);
      if(s.location(s.myAnts[i]).isDead) death--;
    }

  for(unsigned i=0; i!=s.enemyAnts.size(); ++i)
    {
      search_and_kill_t defend(s.enemyAnts[i]);
      fly(s, s.enemyAnts[i], s.attackradius, defend);
      if(s.location(s.enemyAnts[i]).isDead) death++;
    }

  
  return death;
}
